/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package org.is.city.routemanager;

import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.GeometryFactory;
import com.vividsolutions.jts.geom.Point;
import java.awt.geom.Point2D;
import java.io.File;
import java.io.IOException;
import java.io.Serializable;
import java.net.MalformedURLException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JOptionPane;
import org.geotools.data.AbstractFeatureStore;
import org.geotools.data.DataStore;
import org.geotools.data.DataStoreFactorySpi;
import org.geotools.data.DataUtilities;
import org.geotools.data.DefaultTransaction;
import org.geotools.data.FeatureListener;
import org.geotools.data.FeatureSource;
import org.geotools.data.FeatureWriter;
import org.geotools.data.FileDataStore;
import org.geotools.data.FileDataStoreFinder;
import org.geotools.data.Transaction;
import org.geotools.data.memory.MemoryDataStore;
import org.geotools.data.shapefile.ShapefileDataStoreFactory;
import org.geotools.data.simple.SimpleFeatureCollection;
import org.geotools.data.simple.SimpleFeatureIterator;
import org.geotools.feature.DefaultFeatureCollection;
import org.geotools.feature.FeatureCollections;
import org.geotools.feature.simple.SimpleFeatureBuilder;
import org.geotools.feature.simple.SimpleFeatureTypeBuilder;
import org.geotools.geometry.DirectPosition2D;
import org.geotools.geometry.jts.JTSFactoryFinder;
import org.geotools.geosearch.Guide;
import org.geotools.graph.path.Path;
import org.geotools.graph.structure.Edge;
import org.geotools.map.FeatureLayer;
import org.geotools.referencing.crs.EPSGCRSAuthorityFactory;
import org.geotools.styling.BasicLineStyle;
import org.geotools.swing.data.JFileDataStoreChooser;
import org.is.city.MyStyle;
import org.is.city.pointsmanager.RoutePoint;
import org.is.city.routemanager.Layers.PointsLayer;
import org.is.city.routemanager.Layers.RouteLayer;
import org.is.ga.Solver;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;
import org.opengis.referencing.FactoryException;
import org.opengis.referencing.NoSuchAuthorityCodeException;
import org.opengis.referencing.crs.CRSAuthorityFactory;
import org.opengis.referencing.crs.CoordinateReferenceSystem;

/**
 * Фабрика маршрутов
 * @author oleg
 */
public class DefaultRouteFactory extends AbstractRouteFactory {

    MyStyle ms;

    public DefaultRouteFactory(Guide guide) {
        super(guide);
        ms = new MyStyle(MyStyle.GeomType.POINT);
    }

    @Override
    public Route createRoute(DirectPosition2D[] points, OrderType orderType) {
        if (points.length == 0) {
            try {

                DefaultFeatureCollection collection = new DefaultFeatureCollection("ju", guide.getSchema());
                org.geotools.data.store.EmptyFeatureCollection c = new org.geotools.data.store.EmptyFeatureCollection(guide.getSchema());

                FeatureSource f = new AbstractFeatureStore() {

                    @Override
                    public DataStore getDataStore() {
                        DataStore d = new MemoryDataStore(guide.getSchema());
                        return d;
                    }

                    @Override
                    public void addFeatureListener(FeatureListener listener) {
                    }

                    @Override
                    public void removeFeatureListener(FeatureListener listener) {
                    }

                    @Override
                    public SimpleFeatureType getSchema() {
                        return guide.getSchema();
                    }
                };

                collection.add(guide.getInmemory()[0]);
                collection.remove(guide.getInmemory()[0]);
                MyStyle ms = new MyStyle(MyStyle.GeomType.LINE);

                RouteLayer routeLayer = new RouteLayer(f, ms.createPathStyle());
                //Создаем слой точек назначения
                SimpleFeatureCollection pointsSFC = FeatureCollections.newCollection();
                SimpleFeatureTypeBuilder b = new SimpleFeatureTypeBuilder();
                b.setName("Route");
                b.add("name", String.class);
                CRSAuthorityFactory aDefault = EPSGCRSAuthorityFactory.getDefault();
                CoordinateReferenceSystem crs = aDefault.createCoordinateReferenceSystem("EPSG:32637");
                b.setCRS(crs);
                //add some geometry properties (first added is the default)
                b.add("destination", Point.class);
                b.setDefaultGeometry("destination");
                PointsLayer pointsLayer = new PointsLayer(f, new BasicLineStyle());

                return new Route(routeLayer, pointsLayer);
            } catch (NoSuchAuthorityCodeException ex) {
                Logger.getLogger(DefaultRouteFactory.class.getName()).log(Level.SEVERE, null, ex);
            } catch (FactoryException ex) {
                Logger.getLogger(DefaultRouteFactory.class.getName()).log(Level.SEVERE, null, ex);
            }
        } else if (points.length == 2) {
            try {
                Path path = guide.guidance(new Point2D.Double(points[0].x, points[0].y), new Point2D.Double(points[1].x, points[1].y));
                if (path == null) {
                    System.out.println("Путь не найден " + Math.random() * 100);
                    return null;
                }
                SimpleFeatureCollection features = FeatureCollections.newCollection();
                for (Iterator e = path.getEdges().iterator(); e.hasNext();) {
                    Edge edge = (Edge) e.next();
                    SimpleFeature pathFeature = (SimpleFeature) edge.getObject();
                    features.add(pathFeature);
                }
                MyStyle ms = new MyStyle(MyStyle.GeomType.LINE);
                RouteLayer routeLayer = new RouteLayer(features, ms.createPathStyle(), "my path route");
                //Создаем слой точек назначения
                SimpleFeatureCollection pointsSFC = FeatureCollections.newCollection();
                SimpleFeatureTypeBuilder b = new SimpleFeatureTypeBuilder();
                b.setName("Route");
                b.add("name", String.class);
                CRSAuthorityFactory aDefault = EPSGCRSAuthorityFactory.getDefault();
                CoordinateReferenceSystem crs = aDefault.createCoordinateReferenceSystem("EPSG:32637");
                b.setCRS(crs);
                //add some geometry properties (first added is the default)
                b.add("destination", Point.class);
                b.setDefaultGeometry("destination");
                /*
                 * почему-то сначала без attribute desciptor не рисовалось, а теперь все ок!?
                AttributeTypeBuilder build = new AttributeTypeBuilder();
                build.setNillable(true);
                build.setBinding(Point2D.class);

                AttributeDescriptor descriptor = build.buildDescriptor( "destination" );
                //b.add(descriptor);

                 *
                 */
                SimpleFeatureType buildFeatureType = b.buildFeatureType();
                for (int i = 0; i < points.length; i++) {
                    SimpleFeatureBuilder builder = new SimpleFeatureBuilder(buildFeatureType);
                    //builder.add("hello");
                    builder.add("point" + i);
                    GeometryFactory geometryFactory = JTSFactoryFinder.getGeometryFactory(null);

                    Coordinate coord = new Coordinate(points[i].x, points[i].y);
                    Point point = geometryFactory.createPoint(coord);
                    builder.add(point);
                    SimpleFeature buildFeature = builder.buildFeature(null);
                    pointsSFC.add(buildFeature);
                }
                PointsLayer pointsLayer = new PointsLayer(pointsSFC, ms.createPointStyle(pointsSFC.getSchema().getGeometryDescriptor()), "destionation layer");
                return new Route(routeLayer, pointsLayer);
            } catch (NoSuchAuthorityCodeException ex) {
                Logger.getLogger(DefaultRouteFactory.class.getName()).log(Level.SEVERE, null, ex);
            } catch (FactoryException ex) {
                Logger.getLogger(DefaultRouteFactory.class.getName()).log(Level.SEVERE, null, ex);
            }



        } else {
            try {
                int[] solve = null;
                if (orderType == OrderType.NOTORDERED) {
                    DirectPosition2D pointsOptimized[] = new DirectPosition2D[points.length - 1];
                    System.arraycopy(points, 1, pointsOptimized, 0, points.length - 1);
                    Solver solver = new Solver(buildMatrix(points), (int) Math.pow(points.length, 3));
                    solve = solver.solve();
                } else {
                    solve = new int[points.length];
                    for (int i = 0; i < points.length; i++) {
                        solve[i] = i;
                    }
                }
                SimpleFeatureCollection features = FeatureCollections.newCollection();

                for (int i = 0; i < solve.length - 1; i++) {
                    Path path = guide.guidance(new Point2D.Double(points[solve[i]].x, points[solve[i]].y), new Point2D.Double(points[solve[i + 1]].x, points[solve[i + 1]].y));
                    for (Iterator e = path.getEdges().iterator(); e.hasNext();) {
                        Edge edge = (Edge) e.next();
                        SimpleFeature pathFeature = (SimpleFeature) edge.getObject();
                        features.add(pathFeature);
                    }
                }
                MyStyle ms = new MyStyle(MyStyle.GeomType.LINE);
                RouteLayer routeLayer = new RouteLayer(features, ms.createPathStyle(), "my path route");
                //Создаем слой точек назначения
                SimpleFeatureCollection pointsSFC = FeatureCollections.newCollection();
                SimpleFeatureTypeBuilder b = new SimpleFeatureTypeBuilder();
                b.setName("Route");
                b.add("name", String.class);
                CRSAuthorityFactory aDefault = EPSGCRSAuthorityFactory.getDefault();
                CoordinateReferenceSystem crs = aDefault.createCoordinateReferenceSystem("EPSG:32637");
                b.setCRS(crs);
                //add some geometry properties (first added is the default)
                b.add("destination", Point.class);
                b.setDefaultGeometry("destination");
                /*
                 * почему-то сначала без attribute desciptor не рисовалось, а теперь все ок!?
                AttributeTypeBuilder build = new AttributeTypeBuilder();
                build.setNillable(true);
                build.setBinding(Point2D.class);
                AttributeDescriptor descriptor = build.buildDescriptor( "destination" );
                //b.add(descriptor);
                 *
                 */
                SimpleFeatureType buildFeatureType = b.buildFeatureType();
                for (int i = 0; i < points.length; i++) {
                    SimpleFeatureBuilder builder = new SimpleFeatureBuilder(buildFeatureType);
                    //builder.add("hello");
                    builder.add("point" + i);
                    GeometryFactory geometryFactory = JTSFactoryFinder.getGeometryFactory(null);
                    Coordinate coord = new Coordinate(points[solve[i]].x, points[solve[i]].y);
                    Point point = geometryFactory.createPoint(coord);
                    builder.add(point);
                    SimpleFeature buildFeature = builder.buildFeature(null);
                    pointsSFC.add(buildFeature);
                }
                PointsLayer pointsLayer = new PointsLayer(pointsSFC, ms.createPointStyle(pointsSFC.getSchema().getGeometryDescriptor()), "destionation layer");
                return new Route(routeLayer, pointsLayer, this);
            } catch (NoSuchAuthorityCodeException ex) {
                Logger.getLogger(DefaultRouteFactory.class.getName()).log(Level.SEVERE, null, ex);
            } catch (FactoryException ex) {
                Logger.getLogger(DefaultRouteFactory.class.getName()).log(Level.SEVERE, null, ex);
            }

        }
        return null;
    }

    private double[][] buildMatrix(DirectPosition2D points[]) {
        double[][] matrix = new double[points.length][points.length];
        for (int i = 0; i < points.length; i++) {
            for (int j = 0; j < points.length; j++) {
                if (i != j) {
                    if (i == 1 && j == 2) {
                        System.out.println("yes");
                    }
                    Path path = guide.guidance(new Point2D.Double(points[i].x, points[i].y), new Point2D.Double(points[j].x, points[j].y));
                    if (path == null) {
                        System.out.println("Ахтунг!");
                    }
                    for (Iterator e = path.getEdges().iterator(); e.hasNext();) {
                        Edge edge = (Edge) e.next();
                        SimpleFeature pathFeature = (SimpleFeature) edge.getObject();
                        matrix[i][j] += (Double) pathFeature.getProperty("LENGTH").getValue();
                    }
                }
            }
        }
        for (int i = 0; i < points.length; i++) {
            matrix[i][i] = Double.POSITIVE_INFINITY;
        }



        return matrix;
    }

    public static void exportCollection(FeatureLayer layer, File file) {
        try {
            CRSAuthorityFactory aDefault = EPSGCRSAuthorityFactory.getDefault();
            CoordinateReferenceSystem worldCRS = aDefault.createCoordinateReferenceSystem("EPSG:32637");

            SimpleFeatureType schema = DataUtilities.simple(layer.getFeatureSource().getSchema());

            DataStoreFactorySpi factory = new ShapefileDataStoreFactory();
            Map<String, Serializable> create = new HashMap<String, Serializable>();
            create.put("url", file.toURI().toURL());
            create.put("create spatial index", Boolean.TRUE);
            DataStore dataStore = factory.createNewDataStore(create);
            SimpleFeatureType featureType = SimpleFeatureTypeBuilder.retype(schema, worldCRS);
            dataStore.createSchema(featureType);

            Transaction transaction = new DefaultTransaction("Reproject");
            FeatureWriter<SimpleFeatureType, SimpleFeature> writer =
                    dataStore.getFeatureWriterAppend(featureType.getTypeName(), transaction);
            SimpleFeatureIterator iterator = DataUtilities.simple(layer.getFeatureSource()).getFeatures().features();
            try {
                while (iterator.hasNext()) {
                    // copy the contents of each feature and transform the geometry
                    SimpleFeature feature = iterator.next();
                    SimpleFeature copy = writer.next();
                    copy.setAttributes(feature.getAttributes());

                    Geometry geometry = (Geometry) feature.getDefaultGeometry();
                    //Geometry geometry2 = JTS.transform(geometry, transform);

                    copy.setDefaultGeometry(geometry);
                    writer.write();
                }
                transaction.commit();
                JOptionPane.showMessageDialog(null, "Export to shapefile complete");
            } catch (Exception problem) {
                problem.printStackTrace();
                transaction.rollback();
                JOptionPane.showMessageDialog(null, "Export to shapefile failed");
            } finally {
                writer.close();
                iterator.close();
                transaction.close();
            }

        } catch (NoSuchAuthorityCodeException ex) {
            Logger.getLogger(SaveRouteAction.class.getName()).log(Level.SEVERE, null, ex);
        } catch (FactoryException ex) {
            Logger.getLogger(SaveRouteAction.class.getName()).log(Level.SEVERE, null, ex);
        } catch (MalformedURLException ex) {
            Logger.getLogger(SaveRouteAction.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            Logger.getLogger(SaveRouteAction.class.getName()).log(Level.SEVERE, null, ex);
        }

    }

    /**
     * Экспорт маршрута в shape файл
     * @param route маршрут
     */
    static public void exportToShapefile(Route route) {

        JFileDataStoreChooser chooser = new JFileDataStoreChooser("shp");
        chooser.setDialogTitle("Save reprojected shapefile");
        int returnVal = chooser.showSaveDialog(null);
        if (returnVal != JFileDataStoreChooser.APPROVE_OPTION) {
            return;
        }
        File file = chooser.getSelectedFile();
        String absolutePath = file.getAbsolutePath();
        String replace = absolutePath.replace(".shp", "2.shp");
        File file2 = new File(replace);
        exportCollection(route.getRouteLayer(), file);
        exportCollection(route.getPointsLayer(), file2);

    }

    public static Route create(File linearFile, File pointsFile) {
        MyStyle ms = new MyStyle(MyStyle.GeomType.LINE);
        Route route = null;
        if ((linearFile.exists()) && (pointsFile.exists())) {
            try {
                FileDataStore dataStore1 = FileDataStoreFinder.getDataStore(linearFile);
                FileDataStore dataStore2 = FileDataStoreFinder.getDataStore(pointsFile);
                route = new Route(new RouteLayer(dataStore1.getFeatureSource(), ms.createPathStyle()), new PointsLayer(dataStore2.getFeatureSource(), ms.createPointStyle(dataStore2.getFeatureSource().getSchema().getGeometryDescriptor())));
            } catch (IOException ex) {
                Logger.getLogger(DefaultRouteFactory.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
        return route;
    }

    @Override
    public Route createRoute(List<RoutePoint> points, OrderType orderType) {
        DirectPosition2D dpoints[] = new DirectPosition2D[points.size()];
        int k = 0;
        for (Iterator<RoutePoint> iterator = points.iterator(); iterator.hasNext();) {
            dpoints[k] = iterator.next().getCoordinate();
            k++;
        }

        if (points.isEmpty()) {
            try {

                DefaultFeatureCollection collection = new DefaultFeatureCollection("ju", guide.getSchema());
                org.geotools.data.store.EmptyFeatureCollection c = new org.geotools.data.store.EmptyFeatureCollection(guide.getSchema());

                FeatureSource f = new AbstractFeatureStore() {

                    @Override
                    public DataStore getDataStore() {
                        DataStore d = new MemoryDataStore(guide.getSchema());
                        return d;
                    }

                    @Override
                    public void addFeatureListener(FeatureListener listener) {
                    }

                    @Override
                    public void removeFeatureListener(FeatureListener listener) {
                    }

                    @Override
                    public SimpleFeatureType getSchema() {
                        return guide.getSchema();
                    }
                };

                collection.add(guide.getInmemory()[0]);
                collection.remove(guide.getInmemory()[0]);
                MyStyle ms = new MyStyle(MyStyle.GeomType.LINE);

                RouteLayer routeLayer = new RouteLayer(f, ms.createPathStyle());
                //Создаем слой точек назначения
                SimpleFeatureCollection pointsSFC = FeatureCollections.newCollection();
                SimpleFeatureTypeBuilder b = new SimpleFeatureTypeBuilder();
                b.setName("Route");
                b.add("name", String.class);
                CRSAuthorityFactory aDefault = EPSGCRSAuthorityFactory.getDefault();
                CoordinateReferenceSystem crs = aDefault.createCoordinateReferenceSystem("EPSG:32637");
                b.setCRS(crs);
                //add some geometry properties (first added is the default)
                b.add("destination", Point.class);
                b.setDefaultGeometry("destination");
                PointsLayer pointsLayer = new PointsLayer(f, new BasicLineStyle());

                return new Route(routeLayer, pointsLayer);
            } catch (NoSuchAuthorityCodeException ex) {
                Logger.getLogger(DefaultRouteFactory.class.getName()).log(Level.SEVERE, null, ex);
            } catch (FactoryException ex) {
                Logger.getLogger(DefaultRouteFactory.class.getName()).log(Level.SEVERE, null, ex);
            }
        } else if (points.size() == 2) {
            try {


                Path path = guide.guidance(new Point2D.Double(dpoints[0].x, dpoints[0].y), new Point2D.Double(dpoints[1].x, dpoints[1].y));
                if (path == null) {
                    System.out.println("Путь не найден " + Math.random() * 100);
                    return null;
                }
                SimpleFeatureCollection features = FeatureCollections.newCollection();
                for (Iterator e = path.getEdges().iterator(); e.hasNext();) {
                    Edge edge = (Edge) e.next();
                    SimpleFeature pathFeature = (SimpleFeature) edge.getObject();
                    features.add(pathFeature);
                }
                MyStyle ms = new MyStyle(MyStyle.GeomType.LINE);
                RouteLayer routeLayer = new RouteLayer(features, ms.createPathStyle(), "my path route");
                //Создаем слой точек назначения
                SimpleFeatureCollection pointsSFC = FeatureCollections.newCollection();
                SimpleFeatureTypeBuilder b = new SimpleFeatureTypeBuilder();
                b.setName("Route");
                b.add("name", String.class);
                CRSAuthorityFactory aDefault = EPSGCRSAuthorityFactory.getDefault();
                CoordinateReferenceSystem crs = aDefault.createCoordinateReferenceSystem("EPSG:32637");
                b.setCRS(crs);
                //add some geometry properties (first added is the default)
                b.add("destination", Point.class);
                b.setDefaultGeometry("destination");
                /*
                 * почему-то сначала без attribute desciptor не рисовалось, а теперь все ок!?
                AttributeTypeBuilder build = new AttributeTypeBuilder();
                build.setNillable(true);
                build.setBinding(Point2D.class);

                AttributeDescriptor descriptor = build.buildDescriptor( "destination" );
                //b.add(descriptor);

                 *
                 */
                SimpleFeatureType buildFeatureType = b.buildFeatureType();
                for (int i = 0; i < points.size(); i++) {
                    SimpleFeatureBuilder builder = new SimpleFeatureBuilder(buildFeatureType);
                    //builder.add("hello");
                    builder.add("point" + i);
                    GeometryFactory geometryFactory = JTSFactoryFinder.getGeometryFactory(null);

                    Coordinate coord = new Coordinate(dpoints[i].x, dpoints[i].y);
                    Point point = geometryFactory.createPoint(coord);
                    builder.add(point);
                    SimpleFeature buildFeature = builder.buildFeature(null);
                    pointsSFC.add(buildFeature);
                }
                PointsLayer pointsLayer = new PointsLayer(pointsSFC, ms.createPointStyle(pointsSFC.getSchema().getGeometryDescriptor()), "destionation layer");
                return new Route(routeLayer, pointsLayer);
            } catch (NoSuchAuthorityCodeException ex) {
                Logger.getLogger(DefaultRouteFactory.class.getName()).log(Level.SEVERE, null, ex);
            } catch (FactoryException ex) {
                Logger.getLogger(DefaultRouteFactory.class.getName()).log(Level.SEVERE, null, ex);
            }



        } else {
            try {
                int[] solve = null;
                if (orderType == OrderType.NOTORDERED) {
                    DirectPosition2D pointsOptimized[] = new DirectPosition2D[dpoints.length - 1];
                    System.arraycopy(dpoints, 1, pointsOptimized, 0, dpoints.length - 1);
                    Solver solver = new Solver(buildMatrix(dpoints), (int) Math.pow(dpoints.length, 3));
                    solve = solver.solve();
                } else {
                    solve = new int[dpoints.length];
                    for (int i = 0; i < dpoints.length; i++) {
                        solve[i] = i;
                    }
                }
                SimpleFeatureCollection features = FeatureCollections.newCollection();

                for (int i = 0; i < solve.length - 1; i++) {
                    Path path = guide.guidance(new Point2D.Double(dpoints[solve[i]].x, dpoints[solve[i]].y), new Point2D.Double(dpoints[solve[i + 1]].x, dpoints[solve[i + 1]].y));
                    if (path == null) {
                        System.out.println("Ахтунг!");
                    }
                    for (Iterator e = path.getEdges().iterator(); e.hasNext();) {
                        Edge edge = (Edge) e.next();
                        SimpleFeature pathFeature = (SimpleFeature) edge.getObject();
                        features.add(pathFeature);
                        if (!e.hasNext()) {
                            System.out.println("dsd");
                        }
                    }

                }
                MyStyle ms = new MyStyle(MyStyle.GeomType.LINE);
                RouteLayer routeLayer = new RouteLayer(features, ms.createPathStyle(), "my path route");
                //Создаем слой точек назначения
                SimpleFeatureCollection pointsSFC = FeatureCollections.newCollection();
                SimpleFeatureTypeBuilder b = new SimpleFeatureTypeBuilder();
                b.setName("Route");
                b.add("name", String.class);
                CRSAuthorityFactory aDefault = EPSGCRSAuthorityFactory.getDefault();
                CoordinateReferenceSystem crs = aDefault.createCoordinateReferenceSystem("EPSG:32637");
                b.setCRS(crs);
                //add some geometry properties (first added is the default)
                b.add("destination", Point.class);
                b.setDefaultGeometry("destination");
                /*
                 * почему-то сначала без attribute desciptor не рисовалось, а теперь все ок!?
                AttributeTypeBuilder build = new AttributeTypeBuilder();
                build.setNillable(true);
                build.setBinding(Point2D.class);
                AttributeDescriptor descriptor = build.buildDescriptor( "destination" );
                //b.add(descriptor);
                 *
                 */
                SimpleFeatureType buildFeatureType = b.buildFeatureType();
                for (int i = 0; i < dpoints.length; i++) {
                    SimpleFeatureBuilder builder = new SimpleFeatureBuilder(buildFeatureType);
                    //builder.add("hello");
                    builder.add("point" + i);
                    GeometryFactory geometryFactory = JTSFactoryFinder.getGeometryFactory(null);
                    Coordinate coord = new Coordinate(dpoints[solve[i]].x, dpoints[solve[i]].y);
                    Point point = geometryFactory.createPoint(coord);
                    builder.add(point);
                    SimpleFeature buildFeature = builder.buildFeature(null);
                    pointsSFC.add(buildFeature);
                }
                PointsLayer pointsLayer = new PointsLayer(pointsSFC, ms.createPointStyle(pointsSFC.getSchema().getGeometryDescriptor()), "destionation layer");
                return new Route(routeLayer, pointsLayer, this);
            } catch (NoSuchAuthorityCodeException ex) {
                Logger.getLogger(DefaultRouteFactory.class.getName()).log(Level.SEVERE, null, ex);
            } catch (FactoryException ex) {
                Logger.getLogger(DefaultRouteFactory.class.getName()).log(Level.SEVERE, null, ex);
            }

        }
        return null;
    }
}
